package com.futong.cloud.function.client;

import cn.hutool.core.util.ClassUtil;
import com.futong.cloud.action.ActionConsumer;
import com.futong.cloud.action.ActionException;
import com.futong.cloud.utils.ClientUtils;
import com.futong.cloud.utils.ContextUtils;
import com.futong.cloud.utils.Entry;
import com.huaweicloud.sdk.core.ClientBuilder;
import com.huaweicloud.sdk.core.SdkResponse;
import com.huaweicloud.sdk.core.auth.AbstractCredentials;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.region.Region;
import com.huaweicloud.sdk.ecs.v2.EcsClient;
import com.huaweicloud.sdk.ecs.v2.model.CreateServersRequest;
import com.huaweicloud.sdk.ecs.v2.region.EcsRegion;
import com.huaweicloud.sdk.rms.v1.RmsClient;
import com.huaweicloud.sdk.rms.v1.region.RmsRegion;
import javafx.util.Builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;

import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
public class Huawei {
    /***********************************基础配置及缓存*****************************************/
    //缓存模块对应的构造器构造方法以及可调用方法
    static Map<String, Entry.E4<Builder<? extends AbstractCredentials>,Builder<ClientBuilder>,Function<String, Region>,Map<String, Entry.E2<Class,Method>>>> clientClasss=new HashMap<>();
    static {
        clientClasss.put("ecs",new Entry.E4<>(BasicCredentials::new,EcsClient::newBuilder,EcsRegion::valueOf,analysis(EcsClient.class)));
        clientClasss.put("rms",new Entry.E4<>(GlobalCredentials::new,RmsClient::newBuilder, RmsRegion::valueOf,analysis(RmsClient.class)));
    }
    //解析class方法
    static Map<String, Entry.E2<Class,Method>> analysis(Class clazz){
        List<Method> publicMethods = ClassUtil.getPublicMethods(clazz, t -> SdkResponse.class.isAssignableFrom(t.getReturnType()));
        if(CollectionUtils.isEmpty(publicMethods))return null;
        return publicMethods.stream().collect(Collectors.toMap(Method::getName,t->new Entry.E2(t.getParameterTypes()[0],t)));
    }

    //缓存请求client对象
    static Map<String,Object> clients=new ConcurrentHashMap<>();

    /***********************************函数*****************************************/
    public static ActionConsumer send= context -> {
        String clientId = ContextUtils.getValueByFiledName(context,"clientId");
        String regionId = ContextUtils.getValueByFiledName(context,"regionId");
        Object client;
        //从缓存中获取client
        String clientKey=clientId+"_"+context.actionModel.getResourceType()+"_"+regionId;
        Entry.E4<Builder<? extends AbstractCredentials>, Builder<ClientBuilder>, Function<String, Region>, Map<String,Entry.E2<Class, Method>>> clientClass = clientClasss.get(context.getActionModel().getResourceType());
        if(clients.containsKey(clientKey)){
            client=clients.get(clientKey);
        }else{
            if(Objects.isNull(context.cloudClient)) {
                ClientUtils.setCloudClient(clientId,context);
            }
            ICredential auth = clientClass.v1.build()
                    .withAk(context.cloudClient.getUsername())
                    .withSk(context.cloudClient.getPassword());
            client = clientClass.v2.build().withCredential(auth).withRegion(clientClass.v3.apply(regionId)).build();
            clients.put(clientKey,client);
        }
        Entry.E2<Class, Method> methods = clientClass.v4.get(context.getActionModel().getCloudAction());
        try {
            //构建请求对象
            Object request= methods.v1.newInstance();
            //请求对象赋值
            ContextUtils.setValueByScope(context,request,"request");
            //反射发送请求
            Object response = methods.v2.invoke(client,request);
            //将返回结果放入上下文
            context.setResponse(response);
        } catch (Exception e) {
            log.error("send huawei fail request:{},error:{}",context.getRequest(),e);
            throw new ActionException("send h3c fail!",500);
        }
    };

    public static void main(String[] args){
        System.setProperty("https.proxyHost","172.16.62.165");
        System.setProperty("https.proxyPort","13128");
        CreateServersRequest request=new CreateServersRequest();
//        String ak = "F0MEAYBJPEKO62UKEZCP";
//        String sk = "5jEw5Kif1NLvILyADZrm7q6Gg6XiCM5AMaUuIW5N";
////
//        ICredential auth = new BasicCredentials()
//                .withAk(ak)
//                .withSk(sk);
//        EcsClient client = EcsClient.newBuilder()
//                .withCredential(auth)
//                .withRegion(EcsRegion.valueOf("cn-east-2"))
//                .build();
//        NovaListAvailabilityZonesRequest request = new NovaListAvailabilityZonesRequest();
//        NovaListAvailabilityZonesResponse novaListAvailabilityZonesResponse = client.novaListAvailabilityZones(request);

//        Object client = new ClientBuilder(clientClasss.get("ecs")).withCredential(auth).withRegion(EcsRegion.valueOf("cn-east-2")).build();
//        NovaListAvailabilityZonesRequest request = new NovaListAvailabilityZonesRequest();
//        try {
////            NovaListAvailabilityZonesResponse response = client.novaListAvailabilityZones(request);
//            Object response = clientMethods.get(client.getClass()).get("novaListAvailabilityZones").getValue().invoke(client,request);
//            System.out.println(response.toString());
//        } catch (ConnectionException e) {
//            e.printStackTrace();
//        } catch (RequestTimeoutException e) {
//            e.printStackTrace();
//        } catch (ServiceResponseException e) {
//            e.printStackTrace();
//            System.out.println(e.getHttpStatusCode());
//            System.out.println(e.getErrorCode());
//            System.out.println(e.getErrorMsg());
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        } catch (InvocationTargetException e) {
//            e.printStackTrace();
//        }
    }
}
